import 'dart:convert';
import 'dart:developer' as developer;
import 'package:dio/dio.dart';
import 'package:flutter/foundation.dart';
import '../models/api_response.dart';
import '../models/document.dart';
import '../models/document_detail.dart';
import '../models/namespace.dart';
import 'auth_service.dart';
import 'dio_client.dart';

class ApiService {
  // Debug模式和Release模式的baseUrl配置
  static const String _debugBaseUrl = 'http://localhost:18886';
  static const String _releaseBaseUrl = 'https://liufq.cn/api';

  // 根据运行模式自动切换baseUrl
  static String get baseUrl => kDebugMode ? _debugBaseUrl : _releaseBaseUrl;

  // Release模式下不需要忽略证书，Debug模式使用HTTP也不需要
  static bool get allowBadCertificates => false;

  // 获取配置好的 Dio 客户端
  static Dio get _dio => DioClient.getDio(
        allowBadCertificates: allowBadCertificates,
      );

  // 401 错误回调，由 main.dart 设置
  static void Function()? onUnauthorized;

  /// 构建请求头（包含 Authorization）
  static Future<Map<String, String>> _buildHeaders() async {
    final headers = <String, String>{
      'Content-Type': 'application/json',
    };

    // 获取 token 并添加到请求头
    final token = await AuthService.getToken();
    if (token != null && token.isNotEmpty) {
      headers['Authorization'] = 'Bearer $token';
    }

    return headers;
  }

  /// 处理 Dio 错误
  static void _handleDioError(DioException e) {
    if (e.response?.statusCode == 401) {
      developer.log('🚫 Unauthorized (401) - Redirecting to login', name: 'API');
      onUnauthorized?.call();
      throw Exception('未授权，请重新登录');
    }
    developer.log('❌ DioError: ${e.message}', name: 'API');
    throw Exception('网络请求失败: ${e.message}');
  }

  /// 通用请求封装
  /// [method] HTTP方法 (GET, POST, PUT, DELETE)
  /// [path] 请求路径
  /// [data] 请求数据（可选）
  /// [queryParameters] 查询参数（可选）
  /// [parser] 响应数据解析器（可选，用于有返回值的接口）
  /// [allowEmptyResponse] 是否允许空响应（默认false，用于某些更新/删除接口）
  static Future<T?> _request<T>({
    required String method,
    required String path,
    Map<String, dynamic>? data,
    Map<String, dynamic>? queryParameters,
    T Function(dynamic)? parser,
    bool allowEmptyResponse = false,
  }) async {
    final url = '$baseUrl$path';
    developer.log('请求地址: $url', name: 'API');

    try {
      final headers = await _buildHeaders();
      final options = Options(headers: headers);

      Response response;
      switch (method) {
        case 'GET':
          response = await _dio.get(url, queryParameters: queryParameters, options: options);
          break;
        case 'POST':
          response = await _dio.post(url, data: data, queryParameters: queryParameters, options: options);
          break;
        case 'PUT':
          response = await _dio.put(url, data: data, queryParameters: queryParameters, options: options);
          break;
        case 'DELETE':
          response = await _dio.delete(url, data: data, queryParameters: queryParameters, options: options);
          break;
        default:
          throw Exception('不支持的HTTP方法: $method');
      }

      developer.log('请求结果: ${jsonEncode(response.data)}', name: 'API');

      if (response.statusCode == 200) {
        // 处理空响应
        if (response.data == null || response.data.toString().isEmpty) {
          if (allowEmptyResponse) {
            developer.log('✅ Request successful (empty response)', name: 'API');
            return null;
          }
          throw Exception('响应数据为空');
        }

        // 如果没有提供解析器，直接返回null（用于无返回值的接口）
        if (parser == null) {
          return null;
        }

        // 尝试解析 ApiResponse
        try {
          final apiResponse = ApiResponse.fromJson(response.data, parser);
          if (apiResponse.isSuccess && apiResponse.data != null) {
            return apiResponse.data as T;
          }
          throw Exception(apiResponse.message.isEmpty ? '请求失败' : apiResponse.message);
        } catch (e) {
          // 如果是空响应且允许，返回null
          if (allowEmptyResponse) {
            return null;
          }
          rethrow;
        }
      }

      throw Exception('请求失败: ${response.statusCode}');
    } on DioException catch (e) {
      _handleDioError(e);
      rethrow;
    } catch (e) {
      developer.log('❌ Error: $e', name: 'API');
      rethrow;
    }
  }

  Future<List<Document>> getDocumentList({String? namespaceId}) async {
    return await _request<List<Document>>(
      method: 'GET',
      path: '/doc/list',
      queryParameters: namespaceId != null ? {'namespaceId': namespaceId} : null,
      parser: (data) => (data as List<dynamic>)
          .map((e) => Document.fromJson(e as Map<String, dynamic>))
          .toList(),
    ) ?? [];
  }

  Future<DocumentDetail> getDocumentDetail(String id) async {
    final result = await _request<DocumentDetail>(
      method: 'GET',
      path: '/doc/$id',
      parser: (data) => DocumentDetail.fromJson(data as Map<String, dynamic>),
    );
    if (result == null) throw Exception('Failed to load document detail');
    return result;
  }

  Future<void> createDocument(String namespaceId, String name, String content) async {
    await _request(
      method: 'POST',
      path: '/doc',
      data: {
        'namespaceId': namespaceId,
        'name': name,
        'content': content,
      },
    );
  }

  Future<void> updateDocument(String id, String name, String content) async {
    await _request(
      method: 'PUT',
      path: '/doc/$id',
      data: {
        'name': name,
        'content': content,
      },
      allowEmptyResponse: true,
    );
  }

  Future<void> deleteDocument(String id) async {
    await _request(
      method: 'DELETE',
      path: '/doc/$id',
      allowEmptyResponse: true,
    );
  }

  Future<List<Namespace>> getNamespaceList() async {
    return await _request<List<Namespace>>(
      method: 'GET',
      path: '/namespace/list',
      parser: (data) => (data as List<dynamic>)
          .map((e) => Namespace.fromJson(e as Map<String, dynamic>))
          .toList(),
    ) ?? [];
  }
}
